<!DOCTYPE html>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<style>
div * { color: green; }

.a1 ~ .q1#r1,
.a2 ~ x-t2#r2,
.a3 ~ x-t3.q3 span,
.a4 ~ [s4]#r4,
.a5 x-t5[s5],
.a6 ~ [s6].q6,
.a7 ~ [s7].q7#r7,
.a8 ~ x-t8[s8]#r8,
.a9 ~ x-t9[s9].q9 > span,
.a10 > x-t10.q10#r10,
.a11 ~ x-t11:not(#r11b),
.a12 ~ :-webkit-any(.q12, #r12)[s12],
.a13 ~ [s13][s13b] span,
.a14 ~ #r14#r14b,
.a15 *.q15.q15b,
.a16 ~ x-t16:-webkit-any(#r16b, x-t16),
.a17 ~ :-webkit-any(#r17b, x-t17):-webkit-any(x-t17),
.a18 ~ :-webkit-any(.q18, .q18b):-webkit-any(.q18c, .q18d, .q18e) { color: red; }
</style>

<div>
    <!-- class and id -->
    <span class="a1" id="b1"></span>
    <span class="q1"></span>
    <span class="q1" id="r1"></span>
</div>

<div>
    <!-- tag and id -->
    <span class="a2" id="b2"></span>
    <x-t2></x-t2>
    <x-t2 id="r2"></x-t2>
</div>

<div>
    <!-- tag and class -->
    <span class="a3" id="b3"></span>
    <span class="q3"><span></span></span>
    <x-t3><span></span></x-t3>
    <x-t3><span></span></x-t3>
    <x-t3 class="q3"><span id="r3"></span></x-t3>
</div>

<div>
    <!-- attribute and id -->
    <span class="a4" id="b4"></span>
    <span s4="v4"></span>
    <span s4="v4" id="r4"></span>
</div>

<div class="a5" id="b5">
    <!-- tag and attribute -->
    <span s5="v5"></span>
    <x-t5></x-t5>
    <x-t5></x-t5>
    <x-t5 s5="v5" id="r5"></x-t5>
</div>

<div>
    <!-- attribute and class -->
    <span class="a6" id="b6"></span>
    <span s6="v6"></span>
    <span s6="v6"></span>
    <span class="q6"></span>
    <span s6="v6" class="q6" id="r6"></span>
</div>

<div>
    <!-- attribute and class and id -->
    <span class="a7" id="b7"></span>
    <span class="q7"></span>
    <span s7="v7"></span>
    <span s7="v7" class="q7" id="r7"></span>
</div>

<div>
    <!-- tag and attribute and id -->
    <span class="a8" id="b8"></span>
    <span s8="v8"></span>
    <x-t8></x-t8>
    <x-t8 s8="v8" id="r8"></x-t8>
</div>

<div>
    <!-- tag and attribute and class -->
    <span class="a9" id="b9"></span>
    <span s9="v9"><span></span></span>
    <span s9="v9"><span></span></span>
    <span class="q9"><span></span></span>
    <x-t9><span></span></x-t9>
    <x-t9><span></span></x-t9>
    <x-t9><span></span></x-t9>
    <x-t9 s9="v9" class="q9"><span id="r9"></span></x-t9>
</div>

<div class="a10" id="b10">
    <!-- tag and class and id -->
    <span class="q10"></span>
    <x-t10></x-t10>
    <x-t10 class="q10"></x-t10>
    <x-t10 class="q10" id="r10"></x-t10>
</div>

<div>
    <!-- tag and :not() -->
    <span class="a11" id="b11"></span>
    <span></span>
    <span></span>
    <x-t11 id="r11b"></x-t11>
    <x-t11 id="r11"></x-t11>
</div>

<div>
    <!-- :-webkit-any() and attribute -->
    <span class="a12" id="b12"></span>
    <span class="q12"></span>
    <span class="q12"></span>
    <span class="q12"></span>
    <span s12="v12"></span>
    <span s12="v12" id="r12"></span>
</div>

<div>
    <!-- attribute and attribute -->
    <span class="a13" id="b13"></span>
    <span s13="v13"><span></span></span>
    <span s13="v13b"><span></span></span>
    <span s13b="v13b"><span></span></span>
    <span s13="v13" s13b="v13b"><span id="r13"></span></span>
</div>

<div>
    <!-- id and id -->
    <span class="a14" id="b14"></span>
    <span id="r14"></span>
    <span id="r14b"></span>
</div>

<div class="a15" id="b15">
    <!-- class and class -->
    <span></span>
    <span class="q15"></span>
    <span class="q15"></span>
    <span class="q15b"></span>
    <span class="q15 q15b" id="r15"></span>
</div>

<div>
    <!-- tag and :-webkit-any() -->
    <span class="a16" id="b16"></span>
    <span id="r16b"></span>
    <x-t16 id="r16"></x-t16>
</div>

<div>
    <!-- :-webkit-any() and tag -->
    <span class="a17" id="b17"></span>
    <span id="r17b"></span>
    <x-t17 id="r17"></x-t17>
</div>

<div>
    <!-- :-webkit-any() and :-webkit-any() -->
    <span class="a18" id="b18"></span>
    <span class="q18"></span>
    <span class="q18b"></span>
    <span class="q18c"></span>
    <span class="q18c"></span>
    <span class="q18d"></span>
    <span class="q18d"></span>
    <span class="q18e"></span>
    <span class="q18e"></span>
    <span class="q18 q18e" id="r18"></span>
</div>

<script>
'use strict';
const red = 'rgb(255, 0, 0)';
const green = 'rgb(0, 128, 0)';
document.body.offsetTop; // force style calculation

test(function() {
    assert_true(!!window.internals, "This test only works with internals exposed");
}, "internals are exposed");

test(function() {
    assert_equals(getComputedStyle(r1).color, red);
    b1.classList -= "a1";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 1);
    assert_equals(getComputedStyle(r1).color, green);
}, "given class and id, only id is invalidated");

test(function() {
    assert_equals(getComputedStyle(r2).color, red);
    b2.classList -= "a2";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 1);
    assert_equals(getComputedStyle(r2).color, green);
}, "given tag and id, only id is invalidated");

test(function() {
    assert_equals(getComputedStyle(r3).color, red);
    b3.classList -= "a3";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 2);
    assert_equals(getComputedStyle(r3).color, green);
}, "given tag and class, only class is invalidated");

test(function() {
    assert_equals(getComputedStyle(r4).color, red);
    b4.classList -= "a4";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 1);
    assert_equals(getComputedStyle(r4).color, green);
}, "given attribute and id, only id is invalidated");

test(function() {
    assert_equals(getComputedStyle(r5).color, red);
    b5.classList -= "a5";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 2);
    assert_equals(getComputedStyle(r5).color, green);
}, "given tag and attribute, only attribute is invalidated");

test(function() {
    assert_equals(getComputedStyle(r6).color, red);
    b6.classList -= "a6";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 2);
    assert_equals(getComputedStyle(r6).color, green);
}, "given attribute and class, only class is invalidated");

test(function() {
    assert_equals(getComputedStyle(r7).color, red);
    b7.classList -= "a7";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 1);
    assert_equals(getComputedStyle(r7).color, green);
}, "given attribute and class and id, only id is invalidated");

test(function() {
    assert_equals(getComputedStyle(r8).color, red);
    b8.classList -= "a8";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 1);
    assert_equals(getComputedStyle(r8).color, green);
}, "given tag and attribute and id, only id is invalidated");

test(function() {
    assert_equals(getComputedStyle(r9).color, red);
    b9.classList -= "a9";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 2);
    assert_equals(getComputedStyle(r9).color, green);
}, "given tag and attribute and class, only class is invalidated");

test(function() {
    assert_equals(getComputedStyle(r10).color, red);
    b10.classList -= "a10";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 1);
    assert_equals(getComputedStyle(r10).color, green);
}, "given tag and class and id, only id is invalidated");

test(function() {
    assert_equals(getComputedStyle(r11).color, red);
    b11.classList -= "a11";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 2);
    assert_equals(getComputedStyle(r11).color, green);
}, "given tag and :not(), only tag is invalidated");

test(function() {
    assert_equals(getComputedStyle(r12).color, red);
    b12.classList -= "a12";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 2);
    assert_equals(getComputedStyle(r12).color, green);
}, "given :-webkit-any() and attribute, only attribute is invalidated");

test(function() {
    assert_equals(getComputedStyle(r13).color, red);
    b13.classList -= "a13";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 3);
    assert_equals(getComputedStyle(r13).color, green);
}, "given attribute and attribute, only one attribute is invalidated");

test(function() {
    assert_equals(getComputedStyle(r14).color, green);
    b14.classList -= "a14";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 1);
    /* No element satisfies #r14#r14b */
    assert_equals(getComputedStyle(r14).color, green);
    assert_equals(getComputedStyle(r14b).color, green);
}, "given id and id, only one id is invalidated");

test(function() {
    assert_equals(getComputedStyle(r15).color, red);
    b15.classList -= "a15";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 3);
    assert_equals(getComputedStyle(r15).color, green);
}, "given class and class, only one class is invalidated");

test(function() {
    assert_equals(getComputedStyle(r16).color, red);
    b16.classList -= "a16";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 1);
    assert_equals(getComputedStyle(r16).color, green);
}, "given tag and :-webkit-any(), only one tag is invalidated");

test(function() {
    assert_equals(getComputedStyle(r17).color, red);
    b17.classList -= "a17";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 1);
    assert_equals(getComputedStyle(r17).color, green);
}, "given :-webkit-any() and tag, only one tag is invalidated");

test(function() {
    assert_equals(getComputedStyle(r18).color, red);
    b18.classList -= "a18";
    assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 3);
    assert_equals(getComputedStyle(r18).color, green);
}, "given :-webkit-any() and :-webkit-any(), only one :-webkit-any() is invalidated");

</script>
